home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
cpp_libs
/
intrvews
/
xgrab.lha
/
xgrab
/
grabst
/
proper.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-03-06
|
9KB
|
345 lines
/**
GRAB Graph Layout and Browser System
Copyright (c) 1986, 1988 Regents of the University of California
Copyright (c) 1989, Tera Computer Company
**/
/* proper.c contains procedures to make a proper matrix for a digraph. */
#include "malloc.h"
#include "digraph.h"
#include "debug.h"
#include "list.h"
OUTEDGE *get_edge();
make_proper(digraph)
DIGRAPH *digraph;
/**
make_proper makes a proper reachability matrix for digraph.
**/
{
if (debug1)
{
print_size(digraph, "Size before making proper: \n\t");
}
make_closure(digraph); /* compute trasitive closure of succedents */
find_levels(digraph); /* partition into levels */
undo_closure(digraph); /* restore original edges */
shorten_spans(digraph); /* add dummies to shorten spans over one level */
if (debug1)
{
print_size(digraph, "Size after making proper: \n\t");
}
} /* make_proper */
make_closure(digraph)
DIGRAPH *digraph;
/**
make_closure computes the transitive closure of the succeedent set
of each node in digraph.
**/
{
SET *closed_set; /* closed version of the set */
NODE *node; /* the current node */
VNO root_vno; /* vno of current node */
VNO to_vno; /* each to vertex # */
init_set(closed_set);
each_node(digraph, node)
loop
root_vno = Vno(node);
add_element(closed_set, root_vno); /* node is in its closure */
each_element(Succ_set(node), to_vno)
loop
close_set(digraph, closed_set, to_vno, root_vno);
endloop
copy_set(Succ_set(node), closed_set);
clear_set(closed_set);
each_element(Succ_set(node), to_vno) /* fix up antecedents */
loop
add_element(Ante_set(Node(digraph, to_vno)), root_vno);
endloop
endloop
} /* make_closure */
close_set(digraph, closed_set, vno, root_vno)
DIGRAPH *digraph;
SET *closed_set; /* set to add to */
VNO vno; /* next succedent node */
VNO root_vno; /* vno of root node */
/**
close_set adds the closure of vno's succedents to closed_set. If a
cycle is detected, the last edge in the cycle is reversed, to
break the cycle.
**/
{
VNO to_vno; /* each succedent of vno */
if (!in(closed_set, vno))
{
add_element(closed_set, vno);
each_element(Succ_set(Node(digraph, vno)), to_vno)
loop
if (to_vno == root_vno) /* found cycle */
{
int i;
if (debug1)
{
printf("close_set: edge %s to %s completes cycle\n",
Name(Node(digraph, vno)),
Name(Node(digraph, root_vno)));
}
for (i = max_edges(Node(digraph, vno), Node(digraph, root_vno));
i > 0;
i--)
{
if (get_edge(digraph, Node(digraph, vno),
Node(digraph, root_vno), i) != NULL)
{
reverse_edge(digraph, vno, root_vno, i);
}
}
}
else /* no cycle yet */
{
close_set(digraph, closed_set, to_vno, root_vno);
}
endloop
}
} /* close_set */
find_levels(digraph)
DIGRAPH *digraph;
/**
find_levels partitions the nodes of digraph into levels.
**/
{
LIST *difflist; /* list of set differences */
ITEM *diff; /* each diff item */
SET *diff_set; /* each difference */
SET *level_set; /* each level_set */
int levno = 0; /* level_set number for debugging */
NODE *node; /* each node */
init_list(difflist);
init_set(diff_set); /* initialize the set */
each_node(digraph, node)
loop
copy_set(diff_set, Succ_set(node));
intersect(diff_set, Ante_set(node)); /* compute the intersection */
xor(diff_set, Succ_set(node)); /* compute the difference */
add_item(difflist, Vno(node), diff_set);
if (debug)
{
printf("\n\nNode = %s: Succedents: ", Name(node));
print_set(digraph, Succ_set(node));
printf("\nAntecedents: ");
print_set(digraph, Ante_set(node));
printf("\nDifference: ");
print_set(digraph, diff_set);
printf("\n");
}
endloop
init_set(level_set);
do
{
if (debug)
{
printf("\n\nDiff list is: ");
each_item(difflist, diff)
loop
printf(" %s ", Name(Node(digraph, Key(diff))));
endloop
printf("\n\n\nLevel %d: ", levno++);
}
each_item(difflist, diff)
loop
if (empty(Set(diff))) /* no differences */
{
if (debug)
{
printf(" %s ", Name(Node(digraph, Key(diff))));
}
fflush(stdout);
add_element(level_set, Key(diff));
remove_item(difflist, diff);
}
endloop
each_item(difflist, diff)
loop
difference(Set(diff), level_set);
endloop
add_level(digraph, level_set);
clear_set(level_set); /* clear the level_set */
} while (!empty_list(difflist));
{
LEVEL *level; /* each level */
levno = 0;
each_level(digraph, level) /* assign level numbers */
loop
Lno(level) = levno++;
endloop
}
if (debug)
{
print_levels(digraph);
}
} /* find_levels */
undo_closure(digraph)
DIGRAPH *digraph;
/**
undo_closure restores the antecedent and succedent sets of each node in
digraph to their value before make_closure() was invoked. This is done
by traversing the edge list of each node.
**/
{
NODE *node; /* each node */
each_node(digraph, node)
loop
clear_set(Succ_set(node)); /* clear the succedents */
clear_set(Ante_set(node)); /* clear the antecedents */
endloop
fix_ante_succ_sets(digraph);
} /* undo_closure */
shorten_spans(digraph)
DIGRAPH *digraph;
/**
shorten_spans shortens spans with length greater than one by adding dummy
nodes to succeeding levels of digraph.
**/
{
LEVEL *level; /* each level */
MEMBER *member; /* each member */
SET *long_spans; /* set of nodes to have dummies */
SET *ante_set; /* antecedents of dummies */
VNO vno; /* vno of each long span */
init_set(long_spans); /* initialize */
init_set(ante_set);
each_level(digraph, level)
loop
if (Next_level(level) != NULL)
{
each_member(level, member)
loop
/* compute succedents not in the next level */
copy_set(long_spans, Succ_set(Member_node(member)));
difference(long_spans, Members(Next_level(level)));
if (debug)
{
printf("shorten_spans: long spans for '%s': ",
Name(Member_node(member)));
each_element(long_spans, vno)
loop
printf(" %s", Name(Node(digraph, vno)));
endloop
printf("\n");
}
each_element(long_spans, vno)
loop
/* compute antecedents on the current level */
copy_set(ante_set, Ante_set(Node(digraph, vno)));
intersect(ante_set, Members(level));
/**
add a dummy node to the next level --
fix up antecedents
**/
add_dummy(digraph, Next_level(level), vno, ante_set);
if (debug)
{
printf("\n\nshorten_spans: shortened %s -> %s span:\n",
Name(Member_node(member)),
Name(Node(digraph, vno)));
print_levels(digraph);
}
endloop
endloop
}
endloop
if (debug)
{
printf("\nshorten_spans:\n");
print_levels(digraph);
}
} /* shorten_spans */
print_size(digraph, message)
DIGRAPH *digraph;
char *message;
/**
print_size goes through the digraph and counts the number of nodes and
edges, and prints out that information along with the message text.
**/
{
NODE *node;
int n_nodes, n_real, n_dummy, n_coalesced, n_coalescer;
int n_arc;
n_nodes = n_real = n_dummy = n_coalesced = n_coalescer = 0;
n_arc = 0;
all_nodes(digraph, node)
loop
if (Is_dummy(node))
{
n_dummy++;
n_arc++;
}
else if (Coalescer(node))
{
n_coalescer++;
n_arc += card(Succ_set(node));
}
else if (Coalesced(node))
{
n_coalesced++;
}
else
{
n_real++;
n_arc += card(Succ_set(node));
}
endloop
n_nodes = n_real + n_dummy;
printf("%s %d nodes (%d real, %d dummy %d coalescer %d coalesced), %d arcs.\n", message, n_nodes, n_real, n_dummy, n_coalescer, n_coalesced, n_arc);
} /* print_size */